﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Windows;
using Rxx.Labs.Properties;

namespace Rxx.Labs.Reactive.UI
{
	[DisplayName("View Model")]
	[Description("Attaching a view model to a user interface.")]
	public partial class ViewModelLab : BaseLab
	{
		public ViewModelLab()
		{
			this.SetViewModel(() => new LabViewModel());

			InitializeComponent();
		}

#if WINDOWS_PHONE
		private void Submit(object sender, RoutedEventArgs e)
		{
			((LabViewModel) this.GetViewModel()).Submit.Execute(e);
		}
#endif
	}

	public sealed class LabViewModel : Rxx.ViewModel, INotifyPropertyChanged
	{
		public string Words
		{
			get;
			set;
		}

		public CommandSubject Submit
		{
			get
			{
				return submit;
			}
		}

		public string WordsEnteredAndCounter
		{
			get
			{
				return wordsEnteredAndCounter;
			}
			private set
			{
				if (wordsEnteredAndCounter != value)
				{
					wordsEnteredAndCounter = value;

					OnPropertyChanged(new PropertyChangedEventArgs("WordsEnteredAndCounter"));
				}
			}
		}

		private readonly CommandSubject submit = new CommandSubject();
		private string wordsEnteredAndCounter;

		public LabViewModel()
		{
			Words = Text.EnterWordsHere;
		}

		protected override IEnumerable<IDisposable> Attaching()
		{
			if (!IsInDesignMode)
			{
				((BaseLab) Element).TraceLine(Text.AttachingFormat, DateTime.Now.TimeOfDay);
			}

			yield return submit
				.Select(_ => Observable.Interval(TimeSpan.FromSeconds(1)).Select(i => i + " - " + Words))
				.Switch()
				.ObserveOnDispatcher()
				.Subscribe(value => WordsEnteredAndCounter = value);
		}

		protected override void Detaching()
		{
			((BaseLab) Element).TraceLine(Text.DetachingFormat, DateTime.Now.TimeOfDay);
		}

		public event PropertyChangedEventHandler PropertyChanged;

		private void OnPropertyChanged(PropertyChangedEventArgs e)
		{
			var handler = PropertyChanged;

			if (handler != null)
			{
				handler(this, e);
			}
		}
	}
}